/*
@author Gilad Avidov
@brief demostrate use of memory mapped LCD

This a standalone application wich starts at address zero and supports rs232.
*/

#include <mcs51/8051.h>
#include <at89c51ed2.h>
#include <mcs51reg.h>
#include <stdio.h>
#include "lcd.h"
#include "sched.h"
#include "serial.h"
//#include "i2c.h"
//#include "eeprom.h"
#include "timer.h"
#include "space.h"
#include "spi.h"
#include "joystick.h"

//volatile unsigned char ret_adrr_from_timer0_isr;

void test(void)
{
    puts("\n\r test I am here from IRQ\n\r");
}

void Timer0_ISR(void) __interrupt (1) //_naked
{
/*
__asm
	push	acc
	push	b
	push	dpl
	push	dph
	push	(0+2)
	push	(0+3)
	push	(0+4)
	push	(0+5)
	push	(0+6)
	push	(0+7)
	push	(0+0)
	push	(0+1)
	push	psw

    push    acc
    push    b

	mov	psw,#0x00



//	mov	    (0+2),#_test
//	mov	    (0+3),#(_test >> 8)

//	mov	    (0+2),#_sched_tick
//	mov	    (0+3),#(_sched_tick >> 8)
//	push	(0+2)
//	push	(0+3)

//	mov	_TH0,#0xDD
//	mov	_TL0,#0x00
//  reti;


//	mov	    r2,#_sched_tick
//	mov	    r3,#(_sched_tick >> 8)
	mov	    r2,#_test
	mov	    r3,#(_test >> 8)

	mov	psw,#0x00
    mov     a,sp
    subb    a,#15    //one above ret address, up on first "push acc"
    mov     r0,a
    mov     a,r2
    mov     @r0,a
    inc     r0
    mov     a,r3
    mov     @r0,a

__endasm;

    putchar('.');*/

    TH0 = TH0_VAL;  // high counter value
    TL0 = TL0_VAL;  // low counter value

    ++timer0_irq_cnt;
    if (!(timer0_irq_cnt & 0x0F))
        P1_3 = !P1_3;   // LED tenth of timer freq

    sched_tick();
/*
__asm

	pop	b
	pop	acc

	pop	psw
	pop	(0+1)
	pop	(0+0)
	pop	(0+7)
	pop	(0+6)
	pop	(0+5)
	pop	(0+4)
	pop	(0+3)
	pop	(0+2)
	pop	dph
	pop	dpl
	//pop	b
	//pop	acc

	reti           // goto sched_tick
__endasm;*/
}

void SPI_ISR(void) __interrupt (9)
{
    if (SPSTA & SPIF) {
        spi_data=SPDAT;   /* read receive data */
        spi_data_is_done=1;/* set software flag */
    }
    if (SPSTA & SSERR)
        puts("SPI: error: slave\r");
    if (SPSTA & WCOL)
        puts("SPI: error: collision\r");
    if (SPSTA & MODF)
        puts("SPI: error: mode fault\r");
    //puts("SPI_ISR\n\r");
}

_sdcc_external_startup()
{
    // set XRS0 and XRS1 to enable external memory
    AUXR |= 0xC;
    return 0;
}

void INT0_ISR(void) __interrupt (0)
{
    IE0 = 0x0;
    JOYSTICK_INTERRUPT_ENABLE  = 0;
    joystick_was_pressed = 1;
}

void help()
{
    puts("\n\rkey: action\n\r");
    puts("h  : print this message\r");
    puts("?  : print this message\r");
    puts("t  : task list\r");
    puts("f  : dump full state of scheduler\r");
    puts("j  : center joystick\r");
    puts("s  : stop interval timer\r");
    puts("\n\r");
}


void terminal_thread(void)
{
    char data ch;

    while (1) {
        ch = getchar();

        switch (ch) {
        case '?':
        case 'h':
            help();
            break;
        case 'j':
            puts("center joystick\n\r");
            joystick_center();
            break;
        case 's':
            puts("stop timer\n\r press any key to enable\n\r");
            timer0_stop();
            ch = getchar_no_sched();
            puts("run timer\n\r");
            timer0_run();
            break;
        case 't':
            puts("task list:\n\r");
            printf("highest priority pid:0   lowest priority pid:%d\n\r", SCHED_MAX_TASSKS - 1);
            sched_dump_state();
            break;
        case 'f':
            puts("full dump of scheduler:\n\r");
            sched_dump_full_state();
            break;
        default:
            help();
        }
    }
}

void main(void)
{
    EA = 0;              // disable interrupts until fully configured
    serial_init();
    sched_init();
    space_init();
    space_run_multi_threaded();
    sched_fork(terminal_thread);
    help();
    sched_run();
}
